package com.ybg.engine.report.sign;

import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.springframework.jdbc.core.JdbcTemplate;

import com.ybg.engine.config.ScheduleTimeHelper;
import com.ybg.engine.config.SystemConfigHolder;

/**
 * 点名统计
 * 
 * @author lishiwei
 * @data 2017年5月24日
 *
 */
public class SignReportService {

	private SignReportDao dao;

	private ScheduleTimeHelper scheduleTimeHelper;
	
	private SystemConfigHolder systemConfigHolder;

	public SignReportService(JdbcTemplate jdbcTemplate) {
		dao = new SignReportDao(jdbcTemplate);
		scheduleTimeHelper = new ScheduleTimeHelper(jdbcTemplate);
		systemConfigHolder = new SystemConfigHolder(jdbcTemplate);
	}

	/* 日报 */
	public SignReportUniversityPo getDayReport(String day) throws ParseException {
		String schoolYear = scheduleTimeHelper.getCurrentYear();
		String schoolTerm = scheduleTimeHelper.getCurrentTerm();
		return getDayReport(schoolYear, schoolTerm, day);
	}

	/* 日报 */
	public SignReportUniversityPo getDayReport(String schoolYear, String schoolTerm, String day) throws ParseException {
		SignReportUniversityPo po = new SignReportUniversityPo();
		po.setUniversityCode(systemConfigHolder.getStringValue("schoolId"));
		po.setReportCycle(ReportCycleEnum.DAY);
		po.setSchoolYear(schoolYear);
		po.setSchoolTerm(schoolTerm);
		po.setReportTime(day);
		po.setAbsenceNum(dao.countAbsenceNum(day));
		po.setUsageCourseNum(dao.countUsageCourseNum(day));
		po.setUsageStudentNum(dao.countUsageStudentNum(day));
		po.setUsageTeacherNum(dao.countUsageTeacherNum(day));
		// 出勤人次
		long attendanceNum = dao.countAttendanceNum(day);
		// 出勤率 = 出勤人次 / (出勤人次 + 缺勤人次)
		po.setAttendanceRate(division(attendanceNum, attendanceNum + po.getAbsenceNum()));

		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		// 周次
		String cycle = String.valueOf(scheduleTimeHelper.getCycle(format.parse(day)));
		// 星期
		String week = String.valueOf(getWeek(format.parse(day)));
		// 课程数
		po.setCourseNum(dao.countCourseNum(schoolYear, schoolTerm, cycle, week));
		return po;
	}

	/* 周报 */
	public SignReportUniversityPo getWeekReport(String cycle) {
		String schoolYear = scheduleTimeHelper.getCurrentYear();
		String schoolTerm = scheduleTimeHelper.getCurrentTerm();
		return getWeekReport(schoolYear, schoolTerm, cycle);
	}

	/* 周报 */
	public SignReportUniversityPo getWeekReport(String schoolYear, String schoolTerm, String cycle) {
		SignReportUniversityPo po = new SignReportUniversityPo();
		po.setUniversityCode(systemConfigHolder.getStringValue("schoolId"));
		po.setReportCycle(ReportCycleEnum.WEEK);
		po.setSchoolYear(schoolYear);
		po.setSchoolTerm(schoolTerm);
		po.setReportTime(cycle);
		po.setAbsenceNum(dao.countAbsenceNum(schoolYear, schoolTerm, cycle));
		po.setCourseNum(dao.countCourseNum(schoolYear, schoolTerm, cycle));
		po.setUsageCourseNum(dao.countUsageCourseNum(schoolYear, schoolTerm, cycle));
		po.setUsageStudentNum(dao.countUsageStudentNum(schoolYear, schoolTerm, cycle));
		po.setUsageTeacherNum(dao.countUsageTeacherNum(schoolYear, schoolTerm, cycle));
		// 出勤人次
		long attendanceNum = dao.countAttendanceNum(schoolYear, schoolTerm, cycle);
		// 出勤率 = 出勤人次 / (出勤人次 + 缺勤人次)
		po.setAttendanceRate(division(attendanceNum, attendanceNum + po.getAbsenceNum()));
		return po;
	}

	/* 月报 */
	public SignReportUniversityPo getMonthReport(String month) throws ParseException {
		String schoolYear = scheduleTimeHelper.getCurrentYear();
		String schoolTerm = scheduleTimeHelper.getCurrentTerm();
		return getMonthReport(schoolYear, schoolTerm, month);
	}

	/* 月报 */
	public SignReportUniversityPo getMonthReport(String schoolYear, String schoolTerm, String month)
			throws ParseException {
		SignReportUniversityPo po = new SignReportUniversityPo();
		po.setUniversityCode(systemConfigHolder.getStringValue("schoolId"));
		po.setReportCycle(ReportCycleEnum.MONTH);
		po.setSchoolYear(schoolYear);
		po.setSchoolTerm(schoolTerm);
		po.setReportTime(month);

		// 课程数
		long courseNum = 0L;

		// 月报分解为周报统计
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
		// 月份开始-结束日期
		String firstDay = getFirstDay(format.parse(month));
		String lastDay = getLastDay(format.parse(month));
		// 星期
		int weekOfStartDay = getWeek(format.parse(firstDay));
		int weekOfLastDay = getWeek(format.parse(lastDay));
		// 周次
		int cycleOfStartDay = scheduleTimeHelper.getCycle(format.parse(firstDay));
		int cycleOfLastDay = scheduleTimeHelper.getCycle(format.parse(lastDay));
		// 开始周
		courseNum += dao.countCourseNum(schoolYear, schoolTerm, String.valueOf(cycleOfStartDay),
				String.valueOf(weekOfStartDay), "7");
		// 结束周
		courseNum += dao.countCourseNum(schoolYear, schoolTerm, String.valueOf(cycleOfLastDay), "1",
				String.valueOf(weekOfLastDay));
		// 中间周
		for (int cycle = cycleOfStartDay + 1; cycle < cycleOfLastDay; ++cycle) {
			courseNum += dao.countCourseNum(schoolYear, schoolTerm, String.valueOf(cycle));
		}

		po.setCourseNum(courseNum);
		po.setAbsenceNum(dao.countAbsenceNum(month));
		po.setUsageCourseNum(dao.countUsageCourseNum(month));
		po.setUsageStudentNum(dao.countUsageStudentNum(month));
		po.setUsageTeacherNum(dao.countUsageStudentNum(month));
		// 出勤人次
		long attendanceNum = dao.countAttendanceNum(month);
		// 出勤率 = 出勤人次 / (出勤人次 + 缺勤人次)
		po.setAttendanceRate(division(attendanceNum, attendanceNum + po.getAbsenceNum()));
		return po;
	}

	/* 月份第一天 */
	private static String getFirstDay(Date month) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cale = Calendar.getInstance();
		cale.setTime(month);
		// 获取当月的第一天
		cale.add(Calendar.MONTH, 0);
		cale.set(Calendar.DAY_OF_MONTH, 1);
		return format.format(cale.getTime());
	}

	/* 月份最后一天 */
	private static String getLastDay(Date month) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cale = Calendar.getInstance();
		cale.setTime(month);
		// 获取当月的最后一天 即,下个月月初的前一天
		cale.add(Calendar.MONTH, 1);
		cale.set(Calendar.DAY_OF_MONTH, 0);
		return format.format(cale.getTime());
	}

	/* 星期 */
	private static int getWeek(Date day) {
		Calendar cale = Calendar.getInstance();
		cale.setTime(day);
		// 在美国 星期日是一个星期的第一天
		if (cale.get(Calendar.DAY_OF_WEEK) == 1) {
			return 7;
		}
		return cale.get(Calendar.DAY_OF_WEEK) - 1;
	}

	/* 除法 保留2位小数 */
	private static double division(Number numerator, Number denominator) {
		if (numerator == null) {
			throw new java.lang.ArithmeticException("numerator can not allowed null");
		}
		if (denominator == null) {
			throw new java.lang.ArithmeticException("denominator can not allowed null");
		}

		// 设置精确到小数点后2位
		NumberFormat numberFormat = NumberFormat.getInstance();
		numberFormat.setMaximumFractionDigits(2);
		if (numerator.doubleValue() == 0D) {
			return 0D;
		}
		if (denominator.equals(0)) {
			throw new java.lang.ArithmeticException("denominator can not allowed by 0");
		}

		return Double.parseDouble(numberFormat.format(numerator.doubleValue() / denominator.doubleValue() * 100));
	}

}
